package _21_多线程juc._countdownlatch;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

/**
 *
 * 核心参数
 *      count           等待子任务的个数
 * 有两个核心方法
 *      .countDown()    子任务执行完毕后，通知主任务
 *      .await()        主任务在哪等待子任务
 *
 * 应用一：
 *      让 主任务 等待 所有子任务执行完毕后，再继续执行
 * 应用二：
 *      让所有子任务同时执行，打印开始时间
 *
 *      扩展（模拟百米冲刺）
 *          用一个共享 CountDownLatch(1) order 模拟发令枪，
 *          用一个共享 CountDownLatch(n) answer 模拟n个运动员，
 *          多个运动员在开始执行任务前首先 order.await() 集合，等待 order 1=>0 开始执行
 */
public class CountDownLatchTest03 {

    public static void main(String[] args) throws InterruptedException {
        // 定义运动员的人数
        int count = 3;

        // 发令枪，当从 1 到 0，所有 运动员出发
        CountDownLatch order = new CountDownLatch(1);
        // 运动员
        CountDownLatch answer = new CountDownLatch(count);

        Random random = new Random();
        for (int i = 0; i < count; i++) {
            new Thread(() -> {
                try {
                    // 每个线程是一个运动员，等待 发令枪 从 1 到 0
                    order.await();

                    // 运动员出发
                    System.out.println("  " + Thread.currentThread().getName() + " 运动员出发...");

                    // 使用随机数模拟跑步用时时间长短
                    int num = random.nextInt(8);
                    Thread.sleep(num * 1000);
                    System.out.println( "  " + Thread.currentThread().getName() + " 运动员到达终点，用时 " + num + " s");

                    // 执行完毕到 终点 报道，统计成绩
                    answer.countDown();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }

        // 发布 口令
        System.out.printf("口令：预备 -> 跑\n");
        order.countDown();

        // 等待所有运动员到 终点
        answer.await();

        System.out.println("所有运动员已到终点");
    }

}
